home *** CD-ROM | disk | FTP | other *** search
- /*
- * naca.c
- *
- * Created by Alexandre Naaman (hoser@step.polymtl.ca) 30-08-1995
- * Code clean-up, modifications to include more 5-digit sections:
- * Shamim Mohamed (shamim@synopsys.com) Sept. 8 95
- */
-
- #include <stdio.h>
- #include <math.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- #ifndef PI
- #define PI M_PI
- #endif
-
- void
- usage(char *progname)
- {
- fprintf(stderr, "Usage: %s [-n npoints] [-o output-file] <section-name>\n",
- progname);
-
- }
- enum series { four_digit, five_digit };
- enum surface { upper, lower };
-
- struct airfoil {
- char *name;
- float maxor;
- float posmax;
- float thmax;
- int k1;
- enum series serie;
- };
-
- float
- sqr(float x) {
- return x*x;
- }
-
- float
- cube(float x) {
- return x*x*x;
- }
-
- float
- xcoor(float angl)
- {
- return 0.5 + cos(angl)/2.0;
- }
-
- float
- ytfunc(float x, float thmax)
- {
- return thmax * (1.4845*sqrt(x) - 0.63*x - 1.758*sqr(x)+
- 1.4215*cube(x) - 0.5075*sqr(sqr(x)));
- }
-
- void
- camber_four(float *yc, float *slope,
- float x, float maxor, float posmax)
- {
- if (x < posmax) {
- *yc = maxor/sqr(posmax) * (2.0*posmax*x - sqr(x));
- *slope = 2*(maxor/posmax) * (1.0-(x/posmax));
- }
- else {
- *yc = maxor/sqr(1.0-posmax) * ( 1 - 2*posmax + 2*posmax*x - sqr(x));
- *slope = 2*(maxor/sqr(1-posmax))*(posmax-x);
- }
- }
-
- void
- camber_five(float *yc, float *slope,
- float x, float maxor, float posmax, int k1)
- {
- if (x < maxor) {
- *yc = (1.0/6.0)*k1*(cube(x) - 3.0*maxor*sqr(x) + sqr(maxor)*(3.0-maxor)*x);
- *slope = (1.0/6.0)*k1*( 3.0*sqr(x) - 6.0*maxor*x +
- sqr(maxor)*(3.0-maxor) );
- }
- else {
- *yc = (1.0/6.0)*k1*cube(maxor)*(1.0-x);
- *slope = (1.0/6.0)*k1*cube(maxor);
- }
- }
-
- void
- out_point(float x, float yc, float yt, float slope, enum surface side,
- FILE *fp)
- {
- float xloc, yloc, h;
-
- #ifdef Debug
- fprintf(stderr, " >>> x: %.4g\tcamber: %.3g\tthickness: %.3g\n", x, yc, yt);
- #endif
-
- h = sqrt(1+sqr(slope));
- if (side == upper) {
- xloc = x - yt*slope/h;
- yloc = yc + yt/h;
- }
- else {
- xloc = x + yt*slope/h;
- yloc = yc - yt/h;
- }
- /* Shove results into file */
- fprintf(fp,"%5.5f %5.5f\n", xloc, yloc);
- }
-
- #define dig(c) ((c)-'0')
-
- /* ref. Abbott and Dozenthoff(?) */
- float cambers[4][5] = {
- { 1.1, 1.5, 1.8, 2.1, 2.3 },
- { 0.0, 2.3, 2.8, 3.1, 0.0 },
- { 0.0, 3.1, 3.7, 4.2, 0.0 },
- { 0.0, 4.6, 5.5, 6.2, 0.0 } };
-
- void
- get_params(struct airfoil *data, const char *name)
- {
- data->name = name;
- if(strlen(name) == 4) {
- data->serie = four_digit;
- data->maxor = dig(name[0])/100.0;
- data->posmax = dig(name[1])/10.0;
- data->thmax = atoi(name+2)/100.0;
- }
- else {
- int d1, d2;
- float max_camber;
-
- data->serie = five_digit;
- data->thmax = atoi(name+3)/100.0;
- d1 = dig(name[0]); d2 = dig(name[1]);
- data->posmax = d2/20.0;
- if(name[2] == '0') {
- max_camber = cambers[d1-2][d2-1];
- /* what the hell is this k1? And the the max camber points don't
- // seem to correspond with the this code.... */
- data->maxor = max_camber;
- /*
- switch (code) {
- case 210: data->maxor=.058; data->posmax=.05; data->k1=361.4; break;
- case 220: data->maxor=.126; data->posmax=.1; data->k1=51.64; break;
- case 230: data->maxor=.2025;data->posmax=.15; data->k1=15.957;break;
- case 240: data->maxor=.290; data->posmax=.2; data->k1=6.643; break;
- case 250: data->maxor=.391; data->posmax=.25; data->k1=3.23; break;
- default: break;
- }
- */
- }
- /* else ... */
- }
- }
-
- void
- draw_surface(int nbrdiv, const struct airfoil *data, enum surface side,
- FILE *fp)
- {
- float angl;
- float ainc = PI / nbrdiv;
- int curnbr = nbrdiv;
- float x, yt, yc, slope;
-
- if (side == upper) {
- angl = PI; ainc = - PI / nbrdiv;
- }
- else {
- angl = 0.0; ainc = PI / nbrdiv;
- }
-
- for(; curnbr-- > 0; angl += ainc) {
- x = xcoor(angl);
- yt = ytfunc(x, data->thmax);
- if (data->serie == four_digit)
- camber_four(&yc, &slope, x, data->maxor, data->posmax);
- else
- camber_five(&yc, &slope, x, data->maxor, data->posmax, data->k1);
- out_point(x, yc, yt, slope, side, fp);
- }
- }
-
- /*
- * Check to see if this is a valid name for an NACA section
- */
- char *
- check_name(char *name)
- {
- int len;
-
- /* Trim off a leading NACA or naca */
- if(!strncmp(name, "NACA", 4) || !strncmp(name, "naca", 4))
- name += 4;
-
- len = strlen(name);
-
- if(len < 4 || len > 5) {
- return 0;
- }
-
- if(len == 4) {
- /* Need to all be numeric */
- int i;
- for(i = 0; i < 4; i++)
- if(!isdigit(name[i]))
- return 0;
- }
- else {
- /* Ok, first digit has to be 2, 3, 4, 6 */
- if(!index("2346", name[0]))
- return 0;
-
- /* Second digit has to be 12345, except if the first digit is [346]
- // then the second can only be [234] */
- if(name[1] < '1' || name[1] > '5')
- return 0;
- if(index("346", name[0]))
- if(!index("234", name[1]))
- return 0;
-
- /* Third digit has to be 0 or 1 */
- if(name[2] < '0' || name[2] > '1')
- return 0;
-
- /* We don't know how to do reflexed camber... */
- if(name[2] == '1') {
- fputs("Sorry, don't know how to do reflex camber (yet).\n", stderr);
- return 0;
- }
-
- /* last two need to be numeric */
- if(!isdigit(name[3]) || !isdigit(name[4]))
- return 0;
- }
- return name;
- }
-
- int
- generate_naca(char *name, int num, FILE *fp)
- {
- struct airfoil data;
-
- get_params(&data, name);
-
- fprintf(fp, "NACA %s\n", name);
- /* fprintf(fp,"0.0 0.0\n"); */
-
- #ifdef Debug
- fprintf(stderr, "%s:\n camber: %g\n thickness: %g\n max_camber_pos: %g\n series: %s\n",
- data.name, data.maxor, data.thmax, data.posmax,
- ((data.serie == four_digit)? "four digit" : "five digit"));
- #endif
-
- draw_surface(num, &data, upper, fp);
- draw_surface(num, &data, lower, fp);
-
- fprintf(fp, "0.0 0.0\n");
- fclose (fp);
-
- return 0;
- }
-
- int
- main(int argc, char *argv[])
- {
- int argp = 1;
- FILE *fp = stdout;
- int num_points = 20;
- char *name;
-
- if(argc <= 1) {
- usage(argv[0]);
- exit(1);
- }
-
- /*
- * process options
- * right now, we don't have any but ew need to do -n and -o
- */
-
- if(!(name = check_name(argv[argp]))) {
- fprintf(stderr, "%s: \"%s\" is not a valid NACA section name.\n",
- argv[0], argv[argp]);
- exit(0);
- }
-
- /* Open the output file for write */
-
- generate_naca(name, num_points, fp);
- exit(0);
- }
-
-